(function($){

var defaultOptions = {
    valueRange: [0, 1],
    angleRange: [0, 270],
    maxDistance: 200,
    defaultValue: null,
    onchange: function(){}
};

$.fn.knob = function(options){
    var _t = this;
    options = $.extend({}, defaultOptions, options);
    //如果不写默认值，那么使用最小值作为默认值
    if(typeof options.defaultValue !== 'number'){
        options.defaultValue = options.valueRange[0];
    }
    //当前值
    var value;
    var $rotatable = this.find('.rotatable');
        if($rotatable.length === 0) $rotatable = this;

    // function getValueByAngle(angle){
    //     var vr = options.valueRange;
    //     var ar = options.angleRange;
    //     return vr[0] + (vr[1] - vr[0]) * (angle - ar[0]) / (ar[1] - ar[0]);
    // }

    function getAngleByValue(value){
        var vr = options.valueRange;
        var ar = options.angleRange;
        return ar[0] + (ar[1] - ar[0]) * (value - vr[0]) / (vr[1] - vr[0]);
    }

    var start, valueWhenDrag;
    this.draggable({
        helper: function(){
            return $('<div>');
        },
        start: function(e, params){
            valueWhenDrag = value;
            start = params.position;
        },
        drag: function(e, params){
            var _value = _t.getValueByDistance(options, valueWhenDrag, start, params.position);
            _t.setValue(_value);
        },
        stop: function(e, params){
            var _value = _t.getValueByDistance(options, valueWhenDrag, start, params.position);
            _t.setValue(_value);
        }
    });
    this.getValueByDistance = function(options, value, start, end){
        var vr       = options.valueRange;
        var dx       = end.left - start.left;
        var dy       = end.top - start.top;
        var distance = Math.sqrt(dx * dx + dy * dy);
        var isPlus   = dx > dy;
        var _value   = value + (isPlus ? 1 : -1) * (vr[0] + (vr[1] - vr[0]) * distance / options.maxDistance);
        if(_value > vr[1]) _value = vr[1];
        if(_value < vr[0]) _value = vr[0];
        return _value;
    };
    this.setValue = function(val){
        if(val === value) return;
        value = val;
        var angle = getAngleByValue(value);
        $rotatable.css('transform', 'rotate('+angle+'deg)');
        options.onchange(val);
    };
    this.getValue = function(){
        return value;
    };

    requestAnimationFrame(function(){
        _t.setValue(options.defaultValue);
    });
    return this;
};

})(jQuery);